From 1fbd84c81a444b01084150cb334e91a40e67b00f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 20 May 2005 19:34:47 +0000 Subject: [PATCH] bitkeeper revision 1.1492 (428e3bd7k7u4q5iZW-q27Jpez3WzGg) Clean up vbd probing, and include hardware sector size in the probe information. blkback ensures that all requests are aligned to hardware sector size and returns error if this is not so. In blkfront we now have a request_queue per vbd, with hardsect_size set appropriately. It is now once again possible to mount a CDROM in a domU. Signed-off-by: Keir Fraser --- .../arch/xen/drivers/blkif/frontend/vbd.c | 31 +++----- .../drivers/xen/blkback/blkback.c | 8 +++ .../drivers/xen/blkback/vbd.c | 20 +++--- .../drivers/xen/blkfront/blkfront.c | 38 +++++----- .../drivers/xen/blkfront/block.h | 5 +- .../drivers/xen/blkfront/vbd.c | 70 ++++++++++--------- netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c | 12 +--- tools/blktap/parallax-threaded.c | 2 +- tools/blktap/parallax.c | 2 +- xen/include/public/io/blkif.h | 24 ++----- 10 files changed, 104 insertions(+), 108 deletions(-) diff --git a/linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c b/linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c index 530383dbf0..682906bf66 100644 --- a/linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c +++ b/linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c @@ -136,11 +136,6 @@ static int xlvbd_init_device(vdisk_t *xd) major_name = XLSCSI_MAJOR_NAME; max_part = XLSCSI_MAX_PART; - } else if (VDISK_VIRTUAL(xd->info)) { - - major_name = XLVBD_MAJOR_NAME; - max_part = XLVBD_MAX_PART; - } else { /* SMH: hmm - probably a CCISS driver or sim; assume CCISS for now */ @@ -247,8 +242,8 @@ static int xlvbd_init_device(vdisk_t *xd) blk_size[major] = gd->sizes; } - if ( VDISK_READONLY(xd->info) ) - set_device_ro(device, 1); + if ( xd->info & VDISK_READONLY ) + set_device_ro(device, 1); gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XEN; @@ -297,20 +292,16 @@ static int xlvbd_init_device(vdisk_t *xd) gd->sizes[minor] = capacity>>(BLOCK_SIZE_BITS-9); /* Some final fix-ups depending on the device type */ - switch ( VDISK_TYPE(xd->info) ) + if ( xd->info & VDISK_REMOVABLE ) { - case VDISK_TYPE_CDROM: - case VDISK_TYPE_FLOPPY: - case VDISK_TYPE_TAPE: gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; printk(KERN_ALERT "Skipping partition check on %s /dev/%s\n", - VDISK_TYPE(xd->info)==VDISK_TYPE_CDROM ? "cdrom" : - (VDISK_TYPE(xd->info)==VDISK_TYPE_TAPE ? "tape" : - "floppy"), disk_name(gd, MINOR(device), buf)); - break; - - case VDISK_TYPE_DISK: + (xd->info & VDISK_CDROM) ? "cdrom" : "removable", + disk_name(gd, MINOR(device), buf)); + } + else + { /* Only check partitions on real discs (not virtual!). */ if ( gd->flags[minor>>gd->minor_shift] & GENHD_FL_VIRT_PARTNS ) { @@ -320,12 +311,6 @@ static int xlvbd_init_device(vdisk_t *xd) break; } register_disk(gd, device, gd->max_p, &xlvbd_block_fops, capacity); - break; - - default: - printk(KERN_ALERT "XenoLinux: unknown device type %d\n", - VDISK_TYPE(xd->info)); - break; } } diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c index 40cd170e1d..09ff8c245b 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c @@ -623,6 +623,13 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) for ( i = 0; i < nseg; i++ ) { + if ( ((int)preq.sector_number|(int)seg[i].nsec) & + ((bdev_hardsect_size(preq.bdev) >> 9) - 1) ) + { + DPRINTK("Misaligned I/O request from domain %d", blkif->domid); + goto cleanup_and_fail; + } + while ( (bio == NULL) || (bio_add_page(bio, virt_to_page(MMAP_VADDR(pending_idx, i)), @@ -632,6 +639,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i); if ( unlikely(bio == NULL) ) { + cleanup_and_fail: for ( i = 0; i < (nbio-1); i++ ) bio_put(biolist[i]); fast_flush_area(pending_idx, nseg); diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c b/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c index d60a0126b7..2fcc42273e 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c @@ -15,7 +15,7 @@ struct vbd { blkif_vdev_t vdevice; /* what the domain refers to this vbd as */ unsigned char readonly; /* Non-zero -> read-only */ - unsigned char type; /* VDISK_TYPE_xxx */ + unsigned char type; /* VDISK_xxx */ blkif_pdev_t pdevice; /* phys device that this vbd maps to */ struct block_device *bdev; rb_node_t rb; /* for linking into R-B tree lookup struct */ @@ -30,6 +30,7 @@ static inline dev_t vbd_map_devnum(blkif_pdev_t cookie) #else #define vbd_sz(_v) (blk_size[MAJOR((_v)->pdevice)][MINOR((_v)->pdevice)]*2) #define bdev_put(_b) ((void)0) +#define bdev_hardsect_size(_b) 512 #endif void vbd_create(blkif_be_vbd_create_t *create) @@ -78,6 +79,7 @@ void vbd_create(blkif_be_vbd_create_t *create) vbd->vdevice = vdevice; vbd->readonly = create->readonly; + vbd->type = 0; /* Mask to 16-bit for compatibility with old tools */ vbd->pdevice = create->pdevice & 0xffff; @@ -101,8 +103,11 @@ void vbd_create(blkif_be_vbd_create_t *create) return; } - vbd->type = (vbd->bdev->bd_disk->flags & GENHD_FL_CD) ? - VDISK_TYPE_CDROM : VDISK_TYPE_DISK; + if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD ) + vbd->type |= VDISK_CDROM; + if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE ) + vbd->type |= VDISK_REMOVABLE; + #else if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) ) { @@ -110,8 +115,6 @@ void vbd_create(blkif_be_vbd_create_t *create) create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND; return; } - - vbd->type = VDISK_TYPE_DISK; #endif spin_lock(&blkif->vbd_lock); @@ -189,9 +192,10 @@ void destroy_all_vbds(blkif_t *blkif) static void vbd_probe_single( blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd) { - vbd_info->device = vbd->vdevice; - vbd_info->info = vbd->type | (vbd->readonly ? VDISK_FLAG_RO : 0); - vbd_info->capacity = vbd_sz(vbd); + vbd_info->device = vbd->vdevice; + vbd_info->info = vbd->type | (vbd->readonly ? VDISK_READONLY : 0); + vbd_info->capacity = vbd_sz(vbd); + vbd_info->sector_size = bdev_hardsect_size(vbd->bdev); } diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c index 2276959ff7..7d1fb03ab6 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -193,20 +193,21 @@ static void vbd_update(void) } #endif /* ENABLE_VBD_UPDATE */ +static struct xlbd_disk_info *head_waiting = NULL; static void kick_pending_request_queues(void) { - if ( (xlbd_blk_queue != NULL) && - test_bit(QUEUE_FLAG_STOPPED, &xlbd_blk_queue->queue_flags) ) + struct xlbd_disk_info *di; + while ( ((di = head_waiting) != NULL) && !RING_FULL(&blk_ring) ) { - blk_start_queue(xlbd_blk_queue); - /* XXXcl call to request_fn should not be needed but - * we get stuck without... needs investigating - */ - xlbd_blk_queue->request_fn(xlbd_blk_queue); + head_waiting = di->next_waiting; + di->next_waiting = NULL; + /* Re-enable calldowns. */ + blk_start_queue(di->rq); + /* Kick things off immediately. */ + do_blkif_request(di->rq); } } - int blkif_open(struct inode *inode, struct file *filep) { struct gendisk *gd = inode->i_bdev->bd_disk; @@ -277,8 +278,7 @@ int blkif_ioctl(struct inode *inode, struct file *filep, */ static int blkif_queue_request(struct request *req) { - struct xlbd_disk_info *di = - (struct xlbd_disk_info *)req->rq_disk->private_data; + struct xlbd_disk_info *di = req->rq_disk->private_data; unsigned long buffer_ma; blkif_request_t *ring_req; struct bio *bio; @@ -353,6 +353,7 @@ static int blkif_queue_request(struct request *req) */ void do_blkif_request(request_queue_t *rq) { + struct xlbd_disk_info *di; struct request *req; int queued; @@ -369,10 +370,7 @@ void do_blkif_request(request_queue_t *rq) } if ( RING_FULL(&blk_ring) ) - { - blk_stop_queue(rq); - break; - } + goto wait; DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n", req, req->cmd, req->sector, req->current_nr_sectors, @@ -382,7 +380,15 @@ void do_blkif_request(request_queue_t *rq) blkdev_dequeue_request(req); if ( blkif_queue_request(req) ) { - blk_stop_queue(rq); + wait: + di = req->rq_disk->private_data; + if ( di->next_waiting == NULL ) + { + di->next_waiting = head_waiting; + head_waiting = di; + /* Avoid pointless unplugs. */ + blk_stop_queue(rq); + } break; } @@ -451,7 +457,7 @@ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) } blk_ring.rsp_cons = i; - + kick_pending_request_queues(); spin_unlock_irqrestore(&blkif_io_lock, flags); diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h index 459f9d9545..b1ade07026 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h @@ -90,13 +90,16 @@ struct xlbd_major_info { struct xlbd_disk_info { int xd_device; struct xlbd_major_info *mi; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + struct xlbd_disk_info *next_waiting; + request_queue_t *rq; +#endif }; typedef struct xen_block { int usage; } xen_block_t; -extern struct request_queue *xlbd_blk_queue; extern spinlock_t blkif_io_lock; extern int blkif_open(struct inode *inode, struct file *filep); diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c index 9a33656469..303d8ccae4 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c @@ -87,8 +87,6 @@ static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS + #define MAX_VBDS 64 struct list_head vbds_list; -struct request_queue *xlbd_blk_queue = NULL; - #define MAJOR_XEN(dev) ((dev)>>8) #define MINOR_XEN(dev) ((dev) & 0xff) @@ -233,35 +231,33 @@ static struct xlbd_major_info *xlbd_get_major_info(int device) xlbd_alloc_major_info(major, minor, index)); } -static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type) +static int xlvbd_init_blk_queue(struct gendisk *gd, vdisk_t *disk) { - xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock); - if (xlbd_blk_queue == NULL) - return -1; + request_queue_t *rq; - elevator_init(xlbd_blk_queue, "noop"); + rq = blk_init_queue(do_blkif_request, &blkif_io_lock); + if (rq == NULL) + return -1; - /* - * Turn off barking 'headactive' mode. We dequeue - * buffer heads as soon as we pass them to back-end - * driver. - */ - blk_queue_headactive(xlbd_blk_queue, 0); + elevator_init(rq, "noop"); /* Hard sector size and max sectors impersonate the equiv. hardware. */ - blk_queue_hardsect_size(xlbd_blk_queue, 512); - blk_queue_max_sectors(xlbd_blk_queue, 512); + blk_queue_hardsect_size(rq, disk->sector_size); + blk_queue_max_sectors(rq, 512); /* Each segment in a request is up to an aligned page in size. */ - blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); - blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); + blk_queue_segment_boundary(rq, PAGE_SIZE - 1); + blk_queue_max_segment_size(rq, PAGE_SIZE); /* Ensure a merged request will fit in a single I/O ring slot. */ - blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); - blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); + blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST); + blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST); /* Make sure buffer addresses are sector-aligned. */ - blk_queue_dma_alignment(xlbd_blk_queue, 511); + blk_queue_dma_alignment(rq, 511); + + gd->queue = rq; + return 0; } @@ -274,19 +270,20 @@ struct gendisk *xlvbd_alloc_gendisk( di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL); if (di == NULL) - goto out; + return NULL; + memset(di, 0, sizeof(*di)); di->mi = mi; di->xd_device = disk->device; - if ((VDISK_TYPE(disk->info) == VDISK_TYPE_DISK) && + if (((disk->info & (VDISK_CDROM|VDISK_REMOVABLE)) == 0) && ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)) nr_minors = 1 << mi->type->partn_shift; gd = alloc_disk(nr_minors); - if ( !gd ) + if (gd == NULL) goto out; - if ((VDISK_TYPE(disk->info) != VDISK_TYPE_DISK) || (nr_minors > 1)) + if (((disk->info & (VDISK_CDROM|VDISK_REMOVABLE)) != 0) || (nr_minors > 1)) sprintf(gd->disk_name, "%s%c", mi->type->diskname, 'a' + mi->index * mi->type->disks_per_major + (minor >> mi->type->partn_shift)); @@ -302,21 +299,26 @@ struct gendisk *xlvbd_alloc_gendisk( gd->private_data = di; set_capacity(gd, disk->capacity); - if ((xlbd_blk_queue == NULL) && xlvbd_blk_queue_alloc(mi->type)) - goto out_gendisk; + if (xlvbd_init_blk_queue(gd, disk)) { + del_gendisk(gd); + goto out; + } + + di->rq = gd->queue; - if (VDISK_READONLY(disk->info)) + if (disk->info & VDISK_READONLY) set_disk_ro(gd, 1); - if (VDISK_TYPE(disk->info) == VDISK_TYPE_CDROM) - gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; + if (disk->info & VDISK_REMOVABLE) + gd->flags |= GENHD_FL_REMOVABLE; + + if (disk->info & VDISK_CDROM) + gd->flags |= GENHD_FL_CD; - gd->queue = xlbd_blk_queue; add_disk(gd); + return gd; -out_gendisk: - del_gendisk(gd); out: kfree(di); return NULL; @@ -367,6 +369,7 @@ static int xlvbd_device_del(struct lvdisk *disk) struct gendisk *gd; struct xlbd_disk_info *di; int ret = 0, unused; + request_queue_t *rq; device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device)); @@ -383,7 +386,10 @@ static int xlvbd_device_del(struct lvdisk *disk) goto out; } + rq = gd->queue; del_gendisk(gd); + put_disk(gd); + blk_cleanup_queue(rq); xlvbd_device_free(disk); out: diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c index 23a96241d3..101332691c 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c @@ -476,17 +476,11 @@ get_xbda(vdisk_t *xd) case XEN_IDE7_MAJOR: case XEN_IDE8_MAJOR: case XEN_IDE9_MAJOR: - switch (VDISK_TYPE(xd->info)) { - case VDISK_TYPE_CDROM: + if (xd->info & VDISK_CDROM) return &cd_ata; - case VDISK_TYPE_DISK: - if (xd->capacity == 0) - return NULL; - return &wd_ata; - default: + if (xd->capacity == 0) return NULL; - } - break; + return &wd_ata; #endif default: if (xd->capacity == 0) diff --git a/tools/blktap/parallax-threaded.c b/tools/blktap/parallax-threaded.c index 47e469b111..4944474fc7 100644 --- a/tools/blktap/parallax-threaded.c +++ b/tools/blktap/parallax-threaded.c @@ -250,7 +250,7 @@ int parallax_probe(blkif_request_t *req, blkif_t *blkif) while (vdi) { img_info = (vdisk_t *)MMAP_VADDR(ID_TO_IDX(req->id), 0); img_info[nr_vdis].device = vdi->vdevice; - img_info[nr_vdis].info = VDISK_TYPE_DISK | VDISK_FLAG_VIRT; + img_info[nr_vdis].info = 0; /* The -2 here accounts for the LSB in the radix tree */ img_info[nr_vdis].capacity = ((1LL << (VDI_HEIGHT-2)) >> SECTOR_SHIFT); diff --git a/tools/blktap/parallax.c b/tools/blktap/parallax.c index ee47957ada..dc71b05603 100644 --- a/tools/blktap/parallax.c +++ b/tools/blktap/parallax.c @@ -252,7 +252,7 @@ int parallax_probe(blkif_request_t *req, blkif_t *blkif) while (vdi) { img_info = (vdisk_t *)MMAP_VADDR(ID_TO_IDX(req->id), 0); img_info[nr_vdis].device = vdi->vdevice; - img_info[nr_vdis].info = VDISK_TYPE_DISK | VDISK_FLAG_VIRT; + img_info[nr_vdis].info = 0; /* The -1 here accounts for the LSB in the radix tree */ img_info[nr_vdis].capacity = ((1LL << (VDI_HEIGHT-1)) * SECTS_PER_NODE); diff --git a/xen/include/public/io/blkif.h b/xen/include/public/io/blkif.h index 0f91912bbc..9bc465cf1b 100644 --- a/xen/include/public/io/blkif.h +++ b/xen/include/public/io/blkif.h @@ -83,26 +83,16 @@ DEFINE_RING_TYPES(blkif, blkif_request_t, blkif_response_t); * of vdisk_t elements. */ -/* XXX SMH: Type values below are chosen to match ide_xxx in Linux ide.h. */ -#define VDISK_TYPE_FLOPPY 0x00 -#define VDISK_TYPE_TAPE 0x01 -#define VDISK_TYPE_CDROM 0x05 -#define VDISK_TYPE_OPTICAL 0x07 -#define VDISK_TYPE_DISK 0x20 - -#define VDISK_TYPE_MASK 0x3F -#define VDISK_TYPE(_x) ((_x) & VDISK_TYPE_MASK) - -/* The top two bits of the type field encode various flags. */ -#define VDISK_FLAG_RO 0x40 -#define VDISK_FLAG_VIRT 0x80 -#define VDISK_READONLY(_x) ((_x) & VDISK_FLAG_RO) -#define VDISK_VIRTUAL(_x) ((_x) & VDISK_FLAG_VIRT) +#define VDISK_CDROM 0x1 +#define VDISK_REMOVABLE 0x2 +#define VDISK_READONLY 0x4 -typedef struct { +typedef struct vdisk { blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ u16 info; /* 10: Device type and flags (VDISK_*). */ -} PACKED vdisk_t; /* 12 bytes */ + u16 sector_size; /* 12: Minimum alignment for requests. */ + u16 _pad; +} PACKED vdisk_t; /* 16 bytes */ #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ -- 2.30.2